home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / ULIBOS2.C < prev    next >
C/C++ Source or Header  |  1991-12-08  |  27KB  |  735 lines

  1. /*
  2.    ibmpc/ulibos2.c
  3.  
  4.    DCP OS/2 system-dependent library
  5.  
  6.    Services provided by ulib.c:
  7.  
  8.    - UNIX commands simulation
  9.    - serial I/O
  10.  
  11.    Updated:
  12.  
  13.       14May89  - Added hangup() procedure                               ahd
  14.       21Jan90  - Replaced code for rnews() from Wolfgang Tremmel
  15.                  <tremmel@garf.ira.uka.de> to correct failure to
  16.                  properly read compressed news.                         ahd
  17.    6  Sep 90   - Change logging of line data to printable               ahd
  18.       8 Sep 90 - Split ulib.c into dcplib.c and ulib.c                  ahd
  19.       6 Apr 90 - Create libary for OS/2 from ulib.c                     ahd
  20. */
  21.  
  22. /*--------------------------------------------------------------------*/
  23. /*                        System include files                        */
  24. /*--------------------------------------------------------------------*/
  25.  
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <fcntl.h>
  30. #include <io.h>
  31. #include <time.h>
  32.  
  33. /*--------------------------------------------------------------------*/
  34. /*                         OS/2 include files                         */
  35. /*--------------------------------------------------------------------*/
  36.  
  37. #define INCL_BASE
  38. #include <os2.h>
  39.  
  40. /*--------------------------------------------------------------------*/
  41. /*                    UUPC/extended include files                     */
  42. /*--------------------------------------------------------------------*/
  43.  
  44. #include "lib.h"
  45. #include "ulib.h"
  46. #include "ssleep.h"
  47.  
  48. #include <limits.h>
  49.  
  50. currentfile();
  51.  
  52. boolean   port_active = FALSE;  /* TRUE = port handler handler active  */
  53.  
  54. #define LINELOG "LineData.Log"      /* log serial line data here */
  55.  
  56. static int log_handle;
  57. static int logmode = 0;             /* Not yet logging            */
  58. #define WRITING 1
  59. #define READING 2
  60. static FILE *log_stream;
  61. static boolean hangup_needed = FALSE;
  62.  
  63. static current_baud = 0;
  64.  
  65. #define FAR_NULL ((PVOID) 0L)
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*           Definitions of control structures for DOS API            */
  69. /*--------------------------------------------------------------------*/
  70.  
  71. static HFILE com_handle;
  72. static struct _LINECONTROL com_attrib;
  73. static struct _RXQUEUE com_queue;
  74. static struct _MODEMSTATUS com_signals;
  75. static struct _DCBINFO com_dcbinfo;
  76.  
  77. static BYTE com_status;
  78. static USHORT com_error;
  79. static USHORT usPrevPriority;
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*    o p e n l i n e                                                 */
  83. /*                                                                    */
  84. /*    Open the serial port for I/O                                    */
  85. /*--------------------------------------------------------------------*/
  86.  
  87. int openline(char *name, BPS baud, const boolean direct )
  88. {
  89.    int   value;
  90.    USHORT rc;
  91.    USHORT action;
  92.  
  93.    if (port_active)              /* Was the port already active?     ahd   */
  94.       closeline();               /* Yes --> Shutdown it before open  ahd   */
  95.    if ( port_active )
  96.       panic();
  97.  
  98.    printmsg(15, "openline: %s, %d", name, baud);
  99.  
  100.    if (sscanf(name, "COM%d", &value) != 1)
  101.    {
  102.       printmsg(0,"openline: Communications port must be format COMx, was %s",
  103.          name);
  104.       panic();
  105.    }
  106.  
  107.    rc = DosOpen( name,
  108.                  &com_handle,
  109.                  &action,
  110.                  0L,
  111.                  0 ,
  112.                  FILE_OPEN ,
  113.                  OPEN_FLAGS_FAIL_ON_ERROR |
  114.                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0L );
  115.  
  116.    if ( rc != 0 )
  117.    {
  118.       printmsg(0,"openline: DosOpen error %d on output file %s",
  119.                   (int) rc, name );
  120.       panic();
  121.    }
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*            Reset any errors on the communications port             */
  125. /*--------------------------------------------------------------------*/
  126.  
  127.    rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
  128.                      IOCTL_ASYNC, com_handle);
  129.    if (rc)
  130.    {
  131.       printmsg(0,
  132.             "openline: Unable to read errors for %s, error bits %x",
  133.                name, (int) com_error );
  134.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  135.                (int) rc , (int) rc);
  136.    } /*if */
  137.    else if ( com_error )
  138.       printmsg(0,"openline: Reset errors for %s, error bits were %#04x",
  139.                name, (int) com_error );
  140.  
  141. /*--------------------------------------------------------------------*/
  142. /*                           Set baud rate                            */
  143. /*--------------------------------------------------------------------*/
  144.  
  145.    SIOSpeed(baud);
  146.  
  147. /*--------------------------------------------------------------------*/
  148. /*                        Set line attributes                         */
  149. /*--------------------------------------------------------------------*/
  150.  
  151.    printmsg(15,"openline: Getting attributes");
  152.    rc = DosDevIOCtl( &com_attrib, FAR_NULL, ASYNC_GETLINECTRL, IOCTL_ASYNC,
  153.                 com_handle);
  154.                               /* Get old attributes from device      */
  155.    if (rc)
  156.    {
  157.       printmsg(0,"openline: Unable to get line attributes for %s",name);
  158.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  159.                (int) rc , (int) rc);
  160.       panic();
  161.    } /*if */
  162.  
  163.    com_attrib.bDataBits = 0x08; /* Use eight bit path for data      */
  164.    com_attrib.bParity   = 0x00; /* No parity                        */
  165.    com_attrib.bStopBits = 0x00; /* 1 Stop Bit                       */
  166.  
  167.    printmsg(15,"openline: Setting attributes");
  168.    rc = DosDevIOCtl( FAR_NULL, &com_attrib, ASYNC_SETLINECTRL,
  169.                     IOCTL_ASYNC, com_handle);
  170.    if (rc)
  171.    {
  172.       printmsg(0,"openline: Unable to set line attributes for %s",name);
  173.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  174.                (int) rc , (int) rc);
  175.       panic();
  176.    } /*if */
  177.  
  178. /*--------------------------------------------------------------------*/
  179. /*                        Disable flow control                        */
  180. /*--------------------------------------------------------------------*/
  181.  
  182.    printmsg(15,"openline: Getting flow control information");
  183.    rc = DosDevIOCtl( &com_dcbinfo, FAR_NULL, ASYNC_GETDCBINFO, IOCTL_ASYNC,
  184.                  com_handle);
  185.                               /* Get old attributes from device      */
  186.    if (rc)
  187.    {
  188.       printmsg(0,"openline: Unable to get line attributes for %s",name);
  189.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  190.                (int) rc , (int) rc);
  191.       panic();
  192.    } /*if */
  193.  
  194.    com_dcbinfo.usWriteTimeout = 2999;  /* Write timeout 30 seconds   */
  195.    com_dcbinfo.usReadTimeout = 24;     /* Read timeout .25 seconds   */
  196.    com_dcbinfo.fbCtlHndShake = 0;      /* No control/handshake by OS */
  197.    com_dcbinfo.fbFlowReplace = 0;      /* No flow control, either    */
  198.    com_dcbinfo.fbTimeout = MODE_READ_TIMEOUT | MODE_NO_WRITE_TIMEOUT;
  199.  
  200.    printmsg(15,"openline: Setting dcb information");
  201.    rc = DosDevIOCtl( FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO,
  202.                      IOCTL_ASYNC, com_handle);
  203.    if ( rc )
  204.    {
  205.       printmsg(0,"openline: Unable to set flow control for %s",name);
  206.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  207.                (int) rc , (int) rc);
  208.       panic();
  209.    } /*if */
  210.  
  211. /*--------------------------------------------------------------------*/
  212. /*                     Raise Data Terminal Ready                      */
  213. /*--------------------------------------------------------------------*/
  214.  
  215.    com_signals.fbModemOn = DTR_ON | RTS_ON;
  216.    com_signals.fbModemOff = 0xff;
  217.  
  218.    printmsg(15,"openline: Raising RTS/DTR");
  219.    rc = DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  220.                      IOCTL_ASYNC, com_handle);
  221.    if (rc)
  222.    {
  223.       printmsg(0,
  224.             "openline: Unable to raise DTR/RTS for %s, error bits %#x",
  225.                   name, (int) com_error );
  226.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  227.                (int) rc , (int) rc);
  228.       panic();
  229.    } /*if */
  230.  
  231. /*--------------------------------------------------------------------*/
  232. /*        Log serial line data only if log file already exists        */
  233. /*--------------------------------------------------------------------*/
  234.  
  235.    log_handle = open(LINELOG, O_WRONLY | O_TRUNC | O_BINARY);
  236.    if (log_handle != -1) {
  237.       printmsg(15, "openline: logging serial line data to %s", LINELOG);
  238.       log_stream = fdopen(log_handle, "wb");
  239.    }
  240.  
  241.    port_active = TRUE;     /* record status for error handler */
  242.  
  243. /*--------------------------------------------------------------------*/
  244. /*                     Up our processing priority                     */
  245. /*--------------------------------------------------------------------*/
  246.  
  247.    rc = DosGetPrty(PRTYS_PROCESS, &usPrevPriority, 0);
  248.    if (rc)
  249.    {
  250.       printmsg(0,"openline: Unable to get priority for task");
  251.       printmsg(0,"Return code from DosGetPrty was %#04x (%d)",
  252.                (int) rc , (int) rc);
  253.       panic();
  254.    } /*if */
  255.  
  256.    rc = DosSetPrty(PRTYS_PROCESS, PRTYC_TIMECRITICAL, 0, 0);
  257.    if (rc)
  258.    {
  259.       printmsg(0,"openline: Unable to set priority for task");
  260.       printmsg(0,"Return code from DosSetPrty was %#04x (%d)",
  261.                (int) rc , (int) rc);
  262.    } /*if */
  263.  
  264. /*--------------------------------------------------------------------*/
  265. /*                     Wait for port to stablize                      */
  266. /*--------------------------------------------------------------------*/
  267.  
  268.    ddelay(500);            /* Allow port to stablize          */
  269.    return 0;
  270.  
  271. } /*openline*/
  272.  
  273.  
  274. /*--------------------------------------------------------------------*/
  275. /*    s r e a d                                                       */
  276. /*                                                                    */
  277. /*    Read from the serial port                                       */
  278. /*                                                                    */
  279. /*   Non-blocking read essential to "g" protocol.  See "dcpgpkt.c"    */
  280. /*   for description.                                                 */
  281. /*                                                                    */
  282. /*   This all changes in a multi-tasking system.  Requests for I/O    */
  283. /*   should get queued and an event flag given.  Then the             */
  284. /*   requesting process (e.g. gmachine()) waits for the event flag    */
  285. /*   to fire processing either a read or a write.  Could be           */
  286. /*   implemented on VAX/VMS or DG but not MS-DOS.                     */
  287. /*--------------------------------------------------------------------*/
  288.  
  289. unsigned int sread(char *output, unsigned int wanted, unsigned int timeout)
  290. {
  291.    static char save[BUFSIZ];
  292.    static USHORT bufsize = 0;
  293.    USHORT rc;
  294.    time_t stop_time ;
  295.    time_t now ;
  296.  
  297. /*--------------------------------------------------------------------*/
  298. /*           Determine if our internal buffer has the data            */
  299. /*--------------------------------------------------------------------*/
  300.  
  301.    if (bufsize >= wanted)
  302.    {
  303.       memmove( output, save, wanted );
  304.       bufsize -= wanted;
  305.       if ( bufsize )          /* Any data left over?                 */
  306.          memmove( save, &save[wanted], bufsize );  /* Yes --> Save it*/
  307.       return wanted + bufsize;
  308.    } /* if */
  309.  
  310. /*--------------------------------------------------------------------*/
  311. /*            Reset any errors on the communications port             */
  312. /*--------------------------------------------------------------------*/
  313.  
  314.    rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
  315.                      IOCTL_ASYNC, com_handle);
  316.    if (rc)
  317.    {
  318.       printmsg(0,"sread: Unable to read port errors");
  319.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  320.                (int) rc , (int) rc);
  321.    } /*if */
  322.    else if ( com_error )
  323.       printmsg(0,"sread: Reset port error, error bits were %#04x",
  324.                (int) com_error );
  325.  
  326. /*--------------------------------------------------------------------*/
  327. /*                 Determine when to stop processing                  */
  328. /*--------------------------------------------------------------------*/
  329.  
  330.    if ( timeout == 0 )
  331.    {
  332.       stop_time = 0;
  333.       now = 1;                /* Any number greater than stop time   */
  334.    }
  335.    else {
  336.       time( & now );
  337.       stop_time = now + timeout;
  338.    }
  339.  
  340. /*--------------------------------------------------------------------*/
  341. /*            Try to read any needed data into the buffer             */
  342. /*--------------------------------------------------------------------*/
  343.  
  344.    do {
  345.       USHORT needed =  (USHORT) wanted - bufsize;
  346.       USHORT port_timeout;
  347.       USHORT received = 0;
  348.  
  349. /*--------------------------------------------------------------------*/
  350. /*           Compute a new timeout for the read, if needed            */
  351. /*--------------------------------------------------------------------*/
  352.  
  353.       if (stop_time > now )
  354.       {
  355.          port_timeout = (USHORT) (stop_time - now) / needed * 100;
  356.          if (port_timeout < 100)
  357.             port_timeout = 100;
  358.       }
  359.       else
  360.          port_timeout = 0;
  361.  
  362.       if ( port_timeout != com_dcbinfo.usReadTimeout )
  363.       {
  364.          com_dcbinfo.usReadTimeout = port_timeout;
  365.          rc = DosDevIOCtl(FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO,
  366.                           IOCTL_ASYNC, com_handle);
  367.          if ( rc )
  368.          {
  369.             printmsg(0,"sread: Unable to set timeout for comm port");
  370.             printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  371.                      (int) rc , (int) rc);
  372.             panic();
  373.          } /*if */
  374.          printmsg(15,"sread: new port time out is %d seconds/100",
  375.                   port_timeout);
  376.       } /* if */
  377.  
  378. /*--------------------------------------------------------------------*/
  379. /*                 Read the data from the serial port                 */
  380. /*--------------------------------------------------------------------*/
  381.  
  382.       rc = DosRead( com_handle, &save[bufsize], needed, &received );
  383.  
  384.       if ( rc != 0 )
  385.       {
  386.          printmsg(0,"sread: Read from comm port for %d bytes failed.",
  387.                   needed);
  388.          printmsg(0,"Return code from DosRead was %#04x (%d)",
  389.                   (int) rc , (int) rc);
  390.          bufsize = 0;
  391.          return 0;
  392.       }
  393.  
  394.       printmsg(15,"sread: Want %d characters, received %d, total %d in buffer",
  395.             (int) wanted, (int) received, (int) bufsize + received);
  396.  
  397. /*--------------------------------------------------------------------*/
  398. /*                    Log the newly received data                     */
  399. /*--------------------------------------------------------------------*/
  400.  
  401.       if (log_handle != -1)
  402.       {
  403. #ifdef VERBOSE
  404.          size_t column;
  405. #endif
  406.          if (logmode != READING)
  407.          {
  408.             fputs("\nRead:  ", log_stream);
  409.             logmode = READING;
  410.          } /* if */
  411. #ifdef VERBOSE
  412.          for (column = 0; column < received; column++) {
  413.             char s[18];
  414.             itoa(0x100 | (unsigned) save[bufsize + column], s, 16);
  415.                                           /* Make it printable hex   */
  416.             fwrite(s, 1, 2, log_stream);  /* Write hex to the log    */
  417.          } /* for */
  418. #else
  419.          fwrite(&save[bufsize], 1, received, log_stream);
  420. #endif
  421.       } /* if */
  422.  
  423. /*--------------------------------------------------------------------*/
  424. /*            If we got the data, return it to the caller             */
  425. /*--------------------------------------------------------------------*/
  426.  
  427.       bufsize += received;
  428.       if ( bufsize == wanted )
  429.       {
  430.          memmove( output, save, bufsize);
  431.          bufsize = 0;
  432.  
  433.          if (debuglevel > 14)
  434.             fwrite(output,1,bufsize,stdout);
  435.  
  436.          return wanted;
  437.       } /* if */
  438.  
  439. /*--------------------------------------------------------------------*/
  440. /*                 Update the clock for the next pass                 */
  441. /*--------------------------------------------------------------------*/
  442.  
  443.       if (stop_time > 0)
  444.          time( &now );
  445.  
  446.    } while (stop_time > now);
  447.  
  448. /*--------------------------------------------------------------------*/
  449. /*         We don't have enough data; report what we do have          */
  450. /*--------------------------------------------------------------------*/
  451.  
  452.    return bufsize;
  453.  
  454. } /*sread*/
  455.  
  456.  
  457. /*--------------------------------------------------------------------*/
  458. /*    s w r i t e                                                     */
  459. /*                                                                    */
  460. /*    Write to the serial port                                        */
  461. /*--------------------------------------------------------------------*/
  462.  
  463. int swrite(char *data, unsigned int len)
  464. {
  465.    size_t bytes;
  466.    USHORT rc;
  467.  
  468.    hangup_needed = TRUE;      /* Flag that the port is now dirty  */
  469.  
  470. /*--------------------------------------------------------------------*/
  471. /*         Write the data out as the queue becomes available          */
  472. /*--------------------------------------------------------------------*/
  473.  
  474.    rc = DosWrite( com_handle, data , len, &bytes);
  475.    if (rc)
  476.    {
  477.       printmsg(0,"swrite: Write to communications port failed.");
  478.       printmsg(0,"Return code from DosWrite was %#04x (%d)",
  479.                (int) rc , (int) rc);
  480.       return bytes;
  481.    } /*if */
  482.  
  483. /*--------------------------------------------------------------------*/
  484. /*                        Log the data written                        */
  485. /*--------------------------------------------------------------------*/
  486.  
  487.    if (log_handle != -1) {
  488. #ifdef VERBOSE
  489.       char s[18];
  490. #endif
  491.       if (logmode != WRITING)
  492.       {
  493.          fputs("\nWrite: ", log_stream);
  494.          logmode = WRITING;
  495.       }
  496. #ifdef VERBOSE
  497.       for (bytes = 0; bytes < len; bytes++) {
  498.          itoa(0x100 | (unsigned) *data++, s, 16);
  499.                                         /* Make it printable hex  ahd */
  500.          fputc(s[1], log_stream);       /* Put it in the log    */
  501.          fputc(s[2], log_stream);       /* Put it in the log    */
  502.       }
  503. #else
  504.       fwrite(data, 1, len, log_stream);
  505. #endif
  506.    }
  507.  
  508. /*--------------------------------------------------------------------*/
  509. /*            Return bytes written to the port to the caller          */
  510. /*--------------------------------------------------------------------*/
  511.  
  512.    return len;
  513.  
  514. } /*swrite*/
  515.  
  516.  
  517. /*--------------------------------------------------------------------*/
  518. /*    s s e n d b r k                                                 */
  519. /*                                                                    */
  520. /*    send a break signal out the serial port                         */
  521. /*--------------------------------------------------------------------*/
  522.  
  523. void ssendbrk(unsigned int duration)
  524. {
  525.  
  526.    printmsg(12, "ssendbrk: %d", duration);
  527.  
  528.    DosDevIOCtl( &com_error, FAR_NULL, ASYNC_SETBREAKON, IOCTL_ASYNC,
  529.                 com_handle);
  530.    ddelay( duration == 0 ? 200 : duration);
  531.    DosDevIOCtl( &com_error, FAR_NULL, ASYNC_SETBREAKOFF, IOCTL_ASYNC,
  532.                 com_handle);
  533.  
  534. } /*ssendbrk*/
  535.  
  536.  
  537. /*--------------------------------------------------------------------*/
  538. /*    c l o s e l i n e                                               */
  539. /*                                                                    */
  540. /*    Close the serial port down                                      */
  541. /*--------------------------------------------------------------------*/
  542.  
  543. void closeline(void)
  544. {
  545.    USHORT rc;
  546.  
  547.    if ( ! port_active )
  548.       panic();
  549.  
  550.    port_active = FALSE; /* flag port closed for error handler  */
  551.    hangup_needed = FALSE;  /* Don't fiddle with port any more  */
  552.  
  553. /*--------------------------------------------------------------------*/
  554. /*                           Lower priority                           */
  555. /*--------------------------------------------------------------------*/
  556.  
  557.    rc = DosSetPrty(PRTYS_PROCESS,
  558.                    usPrevPriority >> 8 ,
  559.                    usPrevPriority & 0xff, 0);
  560.    if (rc)
  561.    {
  562.       printmsg(0,"closeline: Unable to set priority for task");
  563.       printmsg(0,"Return code from DosSetPrty was %#04x (%d)",
  564.                (int) rc , (int) rc);
  565.    } /*if */
  566.  
  567. /*--------------------------------------------------------------------*/
  568. /*                             Lower DTR                              */
  569. /*--------------------------------------------------------------------*/
  570.  
  571.    com_signals.fbModemOn  = 0x00;
  572.    com_signals.fbModemOff = DTR_OFF | RTS_OFF;
  573.  
  574.  
  575.    if (DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  576.                     IOCTL_ASYNC, com_handle))
  577.    {
  578.       printmsg(0,"closeine: Unable to lower DTR/RTS for %s",name);
  579.    } /*if */
  580.  
  581. /*--------------------------------------------------------------------*/
  582. /*                      Actually close the port                       */
  583. /*--------------------------------------------------------------------*/
  584.  
  585.    rc = DosClose( com_handle );
  586.  
  587.    if ( rc != 0 )
  588.       printmsg( 0,"Close of serial port failed, reason %d", (int) rc);
  589.  
  590. /*--------------------------------------------------------------------*/
  591. /*                   Stop logging the data to disk                    */
  592. /*--------------------------------------------------------------------*/
  593.  
  594.    if (log_handle != -1) {    /* close serial line log file */
  595.       fclose(log_stream);
  596.       close(log_handle);
  597.    };
  598.  
  599.    printmsg(3,"Serial port closed");
  600.  
  601. } /*closeline*/
  602.  
  603.  
  604. /*--------------------------------------------------------------------*/
  605. /*    H a n g u p                                                     */
  606. /*                                                                    */
  607. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  608. /*    many compatibles.                                               */
  609. /*    14 May 89 Drew Derbyshire                                       */
  610. /*--------------------------------------------------------------------*/
  611.  
  612. void hangup( void )
  613. {
  614.    if (!hangup_needed)
  615.       return;
  616.    hangup_needed = FALSE;
  617.  
  618. /*--------------------------------------------------------------------*/
  619. /*                              Drop DTR                              */
  620. /*--------------------------------------------------------------------*/
  621.  
  622.    com_signals.fbModemOn  = 0x00;
  623.    com_signals.fbModemOff = DTR_OFF;
  624.  
  625.    if (DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  626.                      IOCTL_ASYNC, com_handle))
  627.    {
  628.       printmsg(0,"hangup: Unable to lower DTR for comm port");
  629.       panic();
  630.    } /*if */
  631.  
  632. /*--------------------------------------------------------------------*/
  633. /*                  Wait for the telephone to hangup                  */
  634. /*--------------------------------------------------------------------*/
  635.  
  636.    printmsg(3,"hangup: Dropped DTR");
  637.    ddelay(500);            /* Really only need 250 milliseconds         */
  638.  
  639.  
  640. /*--------------------------------------------------------------------*/
  641. /*                          Bring DTR backup                          */
  642. /*--------------------------------------------------------------------*/
  643.  
  644.    com_signals.fbModemOn = DTR_ON;
  645.    com_signals.fbModemOff = 0xff;
  646.  
  647.    if (DosDevIOCtl( &com_error, &com_signals, ASYNC_SETMODEMCTRL,
  648.                      IOCTL_ASYNC, com_handle))
  649.    {
  650.       printmsg(0,"hangup: Unable to raise DTR for comm port");
  651.       panic();
  652.    } /*if */
  653.  
  654.    ddelay(500);            /* Now wait for the poor thing to recover    */
  655.  
  656. }
  657.  
  658.  
  659. /*--------------------------------------------------------------------*/
  660. /* S I O S p e e d                                                    */
  661. /*                                                                    */
  662. /* Re-specify the speed of an opened serial port                      */
  663. /*                                                                    */
  664. /* Dropped the DTR off/on calls because this makes a Hayes drop the   */
  665. /* line if configured properly, and we don't want the modem to drop   */
  666. /* the phone on the floor if we are performing autobaud.              */
  667. /*                                                                    */
  668. /* (Configured properly = standard method of making a Hayes hang up   */
  669. /* the telephone, especially when you can't get it into command state */
  670. /* because it is at the wrong speed or whatever.)                     */
  671. /*--------------------------------------------------------------------*/
  672.  
  673. void SIOSpeed(BPS baud)
  674. {
  675.    USHORT rc;
  676.  
  677.    printmsg(15,"SIOSpeed: Setting baud rate to %d", (int) baud);
  678.    rc = DosDevIOCtl( FAR_NULL, &baud,
  679.                      ASYNC_SETBAUDRATE, IOCTL_ASYNC, com_handle);
  680.    if (rc)
  681.    {
  682.       printmsg(0,"SIOSPeed: Unable to set baud rate for port to %d",
  683.                baud);
  684.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  685.                (int) rc , (int) rc);
  686.       panic();
  687.    } /*if */
  688.  
  689.    current_baud = baud;
  690.  
  691. } /*SIOSpeed*/
  692.  
  693. /*--------------------------------------------------------------------*/
  694. /*    f l o w c o n t r o l                                           */
  695. /*                                                                    */
  696. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  697. /*--------------------------------------------------------------------*/
  698.  
  699.  
  700. void flowcontrol( boolean flow )
  701. {
  702.    USHORT rc;
  703.  
  704.    if ( flow )
  705.        com_dcbinfo.fbFlowReplace = (char)
  706.             (com_dcbinfo.fbFlowReplace |
  707.             (MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE));
  708.    else
  709.       com_dcbinfo.fbFlowReplace = (char)
  710.             (com_dcbinfo.fbFlowReplace &
  711.             (0xff - MODE_AUTO_TRANSMIT - MODE_AUTO_RECEIVE));
  712.  
  713.    rc = DosDevIOCtl( FAR_NULL, &com_dcbinfo, ASYNC_SETDCBINFO,
  714.                      IOCTL_ASYNC, com_handle);
  715.  
  716.    if ( rc )
  717.    {
  718.       printmsg(0,"flowcontrol: Unable to set flow control for %s",name);
  719.       printmsg(0,"Return code from DosDevIOCtl was %#04x (%d)",
  720.                (int) rc , (int) rc);
  721.       panic();
  722.    } /*if */
  723. } /*flowcontrol*/
  724.  
  725. /*--------------------------------------------------------------------*/
  726. /*    G e t S p e e d                                                 */
  727. /*                                                                    */
  728. /*    Report current speed of communications connection               */
  729. /*--------------------------------------------------------------------*/
  730.  
  731. BPS GetSpeed( void )
  732. {
  733.    return current_baud;
  734. } /* GetSpeed */
  735.